#include "json_parser.h"
#include "logging.h"
#include <sstream>


namespace base {

void JsonParser::parseMember(const rapidjson::Value::Member & member, std::map<std::string, std::string> & mapData,
    std::string keyPrefix) {
  if(member.value.IsBool()) {
    std::string v = member.value.GetBool() ? "true": "false";
    mapData[keyPrefix + std::string(member.name.GetString())] = v;
  } else if(member.value.IsNumber()) {
    std::ostringstream os;
    os << member.value.GetInt64();
    mapData[keyPrefix + std::string(member.name.GetString())] = os.str();
  } else if(member.value.IsString()) {
    mapData[keyPrefix + std::string(member.name.GetString())] = member.value.GetString();
  } else if(member.value.IsObject()) {
    keyPrefix += std::string(member.name.GetString()) + ".";
    for(rapidjson::Value::ConstMemberIterator itr = member.value.MemberBegin(); itr != member.value.MemberEnd(); ++itr) {
      parseMember(*itr, mapData, keyPrefix);
    }
  } else if(member.value.IsArray()) {
    int layer = 0;
    for(rapidjson::Value::ConstValueIterator arrayIt = member.value.Begin(); arrayIt != member.value.End(); ++arrayIt) {
      std::ostringstream os;
      os << member.name.GetString() << "." << layer << ".";
      std::string newKeyPrefix = (keyPrefix + os.str());
      for (rapidjson::Value::ConstMemberIterator it = arrayIt->MemberBegin(); it != arrayIt->MemberEnd(); ++it) {
        parseMember(*it, mapData, newKeyPrefix);
      }
      ++layer;
    }
  }
}

bool JsonParser::parse(const std::string & json_data, std::map<std::string, std::string> & output) {
  rapidjson::Document d;
  std::string data(json_data);
  filterIllegalChars(data);
  try {
    if (d.Parse<0>(data.c_str()).HasParseError()) {
      LOG_ERROR("JsonParser::parse --> parse error! json_data:" << json_data << " error:" << d.GetParseError());
      return false;
    }
    for (rapidjson::Value::ConstMemberIterator it = d.MemberBegin(); it != d.MemberEnd(); ++it) {
      parseMember(*it, output, "");
    }
  } catch(std::exception & e) {
    LOG_ERROR("JsonParser::parse --> parse json data failed! error:" << e.what());
    return false;
  }

  return true;
}

bool JsonParser::parseSeq(const std::string & json_data, std::vector<std::map<std::string, std::string> > & output) {
  rapidjson::Document d;
  std::string data(json_data);
  filterIllegalChars(data);
  try {
    d.Parse<0>(data.c_str());
    if(d.HasParseError()) {
      LOG_ERROR("JsonParser::parseSeq --> parse error! jsonData:" << data << " error:" << d.GetParseError());
      return false;
    }
    for(rapidjson::Value::ConstValueIterator arrayIt = d.Begin(); arrayIt != d.End(); ++arrayIt) {
      std::map<std::string, std::string> tmpMap;
      for (rapidjson::Value::ConstMemberIterator it = arrayIt->MemberBegin(); it != arrayIt->MemberEnd(); ++it) {
        parseMember(*it, tmpMap, "");
      }
      output.push_back(tmpMap);
    }
  } catch(std::exception & e) {
    LOG_ERROR("JsonParser::parseSeq --> parse json data failed! error:" << e.what());
    return false;
  }
  return true;
}

}
